package com.cl.springbootfiles.handler;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import jakarta.servlet.ServletContext;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

import java.io.File;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.util.Enumeration;

@Component
public class StartedHandler implements ApplicationListener<ApplicationStartedEvent> {
    private static final Logger log = LoggerFactory.getLogger(StartedHandler.class);
    @Value("${spring.servlet.multipart.location}")
    private String location;
    @Value("${server.port}")
    private int port;
    @Value("${preview.server.url}")
    private String previewServerUrl;
    @Value("${save-path}")
    private String savePath;
    @Value("${clean-days-before}")
    private long cleanDaysBefore;
    private final ServletContext context;

    public StartedHandler(ServletContext context) {
        this.context = context;
    }

    @PostConstruct
    public void init() {
        log.info("文件预览服务地址：{}", this.previewServerUrl);
        log.info("文件预览服务git：{}", "https://gitee.com/kekingcn/file-online-preview");
        this.context.setAttribute("previewServerUrl", this.previewServerUrl);
        String localIp = "127.0.0.1";
        try {
            InetAddress localHostLANAddress = this.getLocalHostLANAddress();
            localIp = localHostLANAddress.getHostAddress();
        } catch (UnknownHostException e) {
            log.error(e.getMessage(), e);
        }
        String qrCodeUrl = "http://" + localIp + ":" + this.port;
        log.info("qrCodeUrl：{}", qrCodeUrl);
        this.context.setAttribute("qrCodeUrl", qrCodeUrl);
        this.context.setAttribute("cleanDaysBefore", this.cleanDaysBefore);
    }

    public void onApplicationEvent(ApplicationStartedEvent event) {
        mkdirs(location);
        mkdirs(savePath);

        log.info(">>>>>文件服务启动成功<<<<<");
    }

    private void mkdirs(String path) {
        File file = new File(path);
        if (!file.exists()) {
            log.info("目录【{}】不存在，程序自动创建。", path);
            file.mkdirs();
        } else if (!file.isDirectory()) {
            log.info("【{}】不是一个目录，程序将删除后自动新建", path);
            FileUtils.deleteQuietly(file);
            file.mkdirs();
        } else {
            log.info("目录【{}】已存在，程序无需处理", path);
        }
    }

    @PreDestroy
    public void destroy() {
        log.info(">>>>>文件服务关闭<<<<<");
    }

    public InetAddress getLocalHostLANAddress() throws UnknownHostException {
        try {
            InetAddress candidateAddress = null;
            // 遍历所有的网络接口
            for (Enumeration ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements(); ) {
                NetworkInterface iface = (NetworkInterface) ifaces.nextElement();
                // 在所有的接口下再遍历IP
                for (Enumeration inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements(); ) {
                    InetAddress inetAddr = (InetAddress) inetAddrs.nextElement();
                    if (!inetAddr.isLoopbackAddress()) {// 排除loopback类型地址
                        if (inetAddr.isSiteLocalAddress()) {
                            // 如果是site-local地址，就是它了
                            return inetAddr;
                        } else if (candidateAddress == null) {
                            // site-local类型的地址未被发现，先记录候选地址
                            candidateAddress = inetAddr;
                        }
                    }
                }
            }
            if (candidateAddress != null) {
                return candidateAddress;
            }
            // 如果没有发现 non-loopback地址.只能用最次选的方案
            InetAddress jdkSuppliedAddress = InetAddress.getLocalHost();
            if (jdkSuppliedAddress == null) {
                throw new UnknownHostException("The JDK InetAddress.getLocalHost() method unexpectedly returned null.");
            }
            return jdkSuppliedAddress;
        } catch (Exception e) {
            UnknownHostException unknownHostException = new UnknownHostException(
                    "Failed to determine LAN address: " + e);
            unknownHostException.initCause(e);
            throw unknownHostException;
        }
    }
}

